#include <limits>

#include "allocator.h"
#include "image2d.h"

namespace Image2D {

Image2D_Imp::Image2D_Imp()
{

}

Image2D_Imp::Image2D_Imp(const void** data, const size_t* linesize, int width, int height, ImageFormat format, ImageType type)
{
    m_width  = width / 2 * 2;
    m_height = height / 2 * 2;
    m_format = format;
    m_type   = type;

    int typesize = typeSize();
    Allocator::alloc2d(m_data, m_linesize, m_width, m_height, m_format, typesize);
    Allocator::copy2d(data, linesize, m_data, m_linesize, m_width, m_height, m_format, typesize);
}

Image2D_Imp::Image2D_Imp(int width, int height, ImageFormat format, ImageType type)
{
    m_width  = width / 2 * 2;
    m_height = height / 2 * 2;
    m_format = format;
    m_type   = type;

    int typesize = typeSize();
    Allocator::alloc2d(m_data, m_linesize, m_width, m_height, m_format, typesize);
}

Image2D_Imp::~Image2D_Imp()
{
    Allocator::free2d(m_data);
}

const int Image2D_Imp::width() const
{
    return m_width;
}

const int Image2D_Imp::height() const
{
    return m_height;
}

const void** Image2D_Imp::data() const
{
    return (const void**)m_data;
}

const void* Image2D_Imp::data(int index) const
{
    return m_data[index];
}

const size_t* Image2D_Imp::linesize() const
{
    return m_linesize;
}

const size_t Image2D_Imp::linesize(int index) const
{
    return m_linesize[index];
}

const ImageFormat Image2D_Imp::format() const
{
    return m_format;
}

const ImageType Image2D_Imp::type() const
{
    return m_type;
}

const int Image2D_Imp::typeSize() const
{
    switch (m_type)
    {
        case ImageType::IMAGE_CHAR:
        case ImageType::IMAGE_UNSIGNED_CHAR:
            return sizeof(char);

        case ImageType::IMAGE_SHORT:
        case ImageType::IMAGE_UNSIGNED_SHORT:
            return sizeof(short);

        case ImageType::IMAGE_INT:
        case ImageType::IMAGE_UNSIGNED_INT:
            return sizeof(int);

        case ImageType::IMAGE_FLOAT:
            return sizeof(float);

        case ImageType::IMAGE_DOUBLE:
            return sizeof(double);
    }

    return 0;
}

}